package main

import (
	"fmt"
	"io"
	"lcnap/flow/cfg"
	"lcnap/flow/log"
	"log/slog"
	"os"
	"os/signal"
	"strconv"
	"syscall"
)

const (
	PidPath string = "logs/flow.pid"
)

var (
	USR1    = syscall.Signal(0xa)
	signals = map[string]syscall.Signal{
		"stop":   syscall.SIGQUIT,
		"quit":   syscall.SIGINT,
		"reload": syscall.SIGHUP,
		"reopen": USR1,
	}
)

func StartApp() {
	arg := cfg.ParseFlag()

	if hasStarted() {
		out := slog.Default()
		//向 运行进程 发送 信号
		pid, err := getRunPid()
		if err != nil {
			out.Error("open pid file failed.", "err", err)
			return
		}
		proc, err := os.FindProcess(pid)
		if err != nil {
			out.Error("failed to find proccess.", "err", err)
			return
		}
		if sig, ok := signals[arg.Singal]; ok {
			err := proc.Signal(sig)
			if err != nil {
				out.Error("failed to send signal.", "err", err)
			}
		} else {
			out.Error("unsupported signal.", "signal", arg.Singal)
		}

		ExitApp()
	}
	savePid()
	conf, err := arg.LoadConfig(arg.ConfigFile)
	if err != nil {
		panic(err)
	}
	logger := log.NewDefaultLogger(arg.ErrorFile)

	logger.Info("server started.", "pid", os.Getpid())
	logger.Info("load", "conf", conf)
}

func ExitApp() {
	clearPid()
	os.Exit(0)
}

func savePid() {
	pid := os.Getpid()
	f, err := os.OpenFile(PidPath, os.O_CREATE|os.O_WRONLY, os.ModePerm)
	if err != nil {
		log.Error("write pid failed.", err)
		return
	}
	defer f.Close()
	f.Seek(0, 0)
	_, err = io.WriteString(f, fmt.Sprintf("%d", pid))
	if err != nil {
		log.Error("write pid failed.", err)
	}
}

func getRunPid() (int, error) {
	f, err := os.Open(PidPath)
	if err != nil {
		return -1, err
	}
	defer f.Close()

	buf, err := io.ReadAll(f)
	if err != nil {
		return -1, err
	}
	spid := string(buf)
	pid, err := strconv.Atoi(spid)
	if err != nil {
		return -1, err
	}
	return pid, nil
}

func clearPid() {
	os.Remove(PidPath)
}

func hasStarted() bool {
	pid, err := getRunPid()
	if err != nil {
		return false
	}
	if pid > 0 {
		return true
	}
	return false
}

func waitSignal() {

	m := map[os.Signal]func(){
		syscall.SIGQUIT: func() {
			clearPid()
			os.Exit(0)
		},
		/* syscall.SIGKILL: func() {
			clearPid()
			os.Exit(0)
		}, */
	}

	sigchan := make(chan os.Signal, 1)
	signal.Notify(sigchan)
	for {
		//处理信号.
		s := <-sigchan
		if f, ok := m[s]; ok {
			log.StdLogger.Info("received signal.", "signal", s)
			f()
		}
	}

}
